//@author A0086393U
package rightnow.logic;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;

import rightnow.storage.Task;

/**
 * This class provides a way for the disparate classes in Logic
 * to give feedback to the users after each command is processed.
 * There is a large number of potential feedback, and we do not want
 * Logic to directly manipulate the UI. Hence, this class was created.
 * 
 * This class uses the observer pattern to update the UI's FeedbackController
 * and ListController whenever Logic updates the message or list stored
 * here. This class also formats the message if necessary (for example, when
 * displaying the message after successfully adding a task by including the 
 * task's description)
 * 
 * This class uses the singleton pattern to ensure only one instance of this
 * class exists at any time. In addition, this removes the need to pass
 * instances of this class throughout wherever in Logic this is called.
 * 
 */
public class FeedbackProvider extends Observable {

	private static FeedbackProvider instance = new FeedbackProvider();
	private String cmdLineMessage;		// holds the message to replace the text
																		// in the cmd line with
	private boolean hasCmdLineChanged;
	private String feedbackMessage;		// holds the message to be displayed
																		// in the feedback line
	private boolean hasFeedbackMsgChanged;
	private List<Task> tasksForUi;		// holds the all tasks for UI to display
	private int totalTasks;						// the total tasks in wholeTaskList
	private int currentPage;					// the current page being displayed
	private int totalPages;						// the total number of pages available
	private boolean hasListChanged;		// whether the list or the content has
																		// changed at all
	private int changedTaskIndex;				// only the contents of one index should
																		// be modified per command. If more than
																		// one task is modified, set mustRefreshList
																		// so the UI will get the whole list
	private String listName;					// The type of list being displayed.
																		// Must be "search term", list all, or now.
	
	
	private FeedbackProvider() {
		super();
		
		feedbackMessage = null;
		tasksForUi = new ArrayList<Task>();
	}
	
	public static FeedbackProvider getInstance() {
		return instance;
	}
	
	/* Logic will use these methods to set the feedback for UI */
	
	/**
	 * Use this to replace the contents of the command line in the UI.
	 * 
	 * @param cmdLine Text to replace the command line's text with
	 */
	protected void setCmdLine(String cmdLine) {
		cmdLineMessage = cmdLine;
		hasCmdLineChanged = true;
		hasFeedbackMsgChanged = false;
		hasListChanged = false;
		setChanged();
		notifyObservers();
	}
	
	/**
	 * Use this to set the contents of the feedback for UI to display.
	 * 
	 * @param msg Feedback for UI to display
	 */
	protected void setMsg(String msg) {
		feedbackMessage = msg;
		hasFeedbackMsgChanged = true;
		hasListChanged = false;
		hasCmdLineChanged = false;
		setChanged();
		notifyObservers();
	}
	
	/**
	 * Use this when you want to change the contents of the entire list, e.g.
	 * after a list or add command.
	 * 
	 * @param tasksToDisplay New page of tasks to be displayed
	 * @param totalTasks Total number of tasks in the whole list
	 * @param currentPage Current page number
	 * @param totalPages Total number of pages in the whole list
	 */
	protected void setList(List<Task> tasksToDisplay, int totalTasks, 
			int currentPage, int totalPages, String listName, int indexToHighlight) {
		hasListChanged = true;
		hasFeedbackMsgChanged = false;
		hasCmdLineChanged = false;

		tasksForUi = tasksToDisplay;
		this.totalTasks = totalTasks;
		this.currentPage = currentPage;
		this.totalPages = totalPages;
		this.listName = listName;
		changedTaskIndex = indexToHighlight;
		
		setChanged();
		notifyObservers();
	}
	
	/* The UI will use the following getters to update the display */
	
	/**
	 * @return cmdLineMessage, meant to replace the text in the command line.
	 */
	public String getCmdLine() {
		return cmdLineMessage;
	}

	/**
	 * @return True if the command line message has changed.
	 */
	public boolean hasCmdLineChanged() {
		return hasCmdLineChanged;
	}
	
	/**
	 * @return feedbackMessage, meant to replace the text in the feedback box.
	 */
	public String getFeedbackMessage() {
		return feedbackMessage;
	}
	
	/**
	 * @return True if the feedback message has changed.
	 */
	public boolean hasFeedbackMsgChanged() {
		return hasFeedbackMsgChanged;
	}
	
	/**
	 * @return List of tasks the UI should display on the page it is on.
	 */
	public List<Task> getTasksForUi() {
		return tasksForUi;
	}
	
	/**
	 * @return Total number of tasks in the full list of tasks to be displayed.
	 */
	public int getTotalTasks() {
		return totalTasks;
	}
	
	/**
	 * @return Current page the list of tasks being displayed is on.
	 */
	public int getCurrentPage() {
		return currentPage;
	}
	
	/**
	 * @return Total number of pages in the full list of tasks to display.
	 */
	public int getTotalPages() {
		return totalPages;
	}

	/**
	 * @return True if the list of tasks to display has been modified.
	 */
	public boolean hasListChanged() {
		return hasListChanged;
	}

	/**
	 * @return The index of the task modified by the latest action. 
	 */
	public int getChangedTaskIndex() {
		return changedTaskIndex;
	}
	
	/**
	 * @return The name of the list of tasks being displayed, "ALL, "NOW", or
	 *         the search term.
	 */
	public String getListName() {	
		return listName;
	}

}
